package com.hung.triple.transport.netty4.handler;

import com.hung.triple.heartbeat.Connection;
import com.hung.triple.heartbeat.NettyHeartBeatHandler;
import com.hung.triple.heartbeat.ServerIdleHandler;
import com.hung.triple.transport.netty4.codec.NettyDecoder;
import com.hung.triple.transport.netty4.codec.NettyEncoder;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * Channel 初始化器
 * 由于 triple 是全双工 RPC 框架，因此 server 和 client 的组件完全相同
 *
 * @author Hung
 * @since 2022/9/18
 */
@Slf4j
@AllArgsConstructor
public class NettyChannelInitializer extends ChannelInitializer<SocketChannel> {

    private boolean isClient;

    private SslContext sslContext;

    /**
     * 是否开启心跳机制
     */
    private boolean heartbeat;

    @Override
    protected void initChannel(SocketChannel ch) {

        ch.attr(Connection.CONNECTION).set(new Connection(ch));
        ch.attr(Connection.HEARTBEAT_SWITCH).set(true);

        ch.pipeline()
                .addFirst(sslContext.newHandler(ch.alloc()))
                .addLast(new NettyChannelSslHandler())
                .addLast(new NettyChannelDuplexHandler(isClient))
                .addLast(new NettyDecoder())
                .addLast(new NettyEncoder())
                .addLast(new NettyRpcRequestHandler());


        //心跳处理器,已经默认开启，可以在全局Config做配置开关
        if (isClient) {
            ch.attr(Connection.HEARTBEAT_COUNT).set(0);

            ch.pipeline().addLast("clientIdleStateHandler", new IdleStateHandler(10, 10, 0));
            ch.pipeline().addLast("heartbeatHandler", new NettyHeartBeatHandler());
        } else {
            ch.pipeline().addLast("serverIdleHandler", new ServerIdleHandler());
            ch.pipeline().addLast("serverIdleStateHandler", new IdleStateHandler(0, 0, 30));
        }


        ch.pipeline()
                .addLast(new NettyRpcResponseHandler(isClient));

    }
}
